package com.zhxq.member.controller;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.dashscope.audio.asr.recognition.Recognition;
import com.alibaba.dashscope.audio.asr.recognition.RecognitionParam;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zhxq.ai.domain.InterviewReport;
import com.zhxq.ai.repository.FileRepository;
import com.zhxq.ai.service.IInterviewReportService;
import com.zhxq.ai.service.TTSService;
import com.zhxq.common.core.controller.BaseController;
import com.zhxq.common.core.domain.AjaxResult;
import com.zhxq.common.core.page.TableDataInfo;
import com.zhxq.common.utils.UserThreadLocal;
import com.zhxq.member.service.IMemberInterviewService;
import com.zhxq.ai.websocket.WebSocketInterviewServer;
import groovy.util.logging.Slf4j;
import io.reactivex.Flowable;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.ai.vectorstore.cassandra.CassandraVectorStore;
import org.springframework.core.io.Resource;
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.ExtractedTextFormatter;
import org.springframework.ai.reader.pdf.PagePdfDocumentReader;
import org.springframework.ai.reader.pdf.config.PdfDocumentReaderConfig;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Objects;
import static com.zhxq.framework.datasource.DynamicDataSourceContextHolder.log;

@RestController
@Tag(name = "客户面试管理")
@RequestMapping("/member/interview")
@Slf4j
@RequiredArgsConstructor
public class MemberInterviewController extends BaseController {

    private final WebSocketInterviewServer webSocketInterviewServer;

    private final FileRepository fileRepository;

    private final VectorStore vectorStore;

    private final IMemberInterviewService memberInterviewService;

    private final TTSService ttsService;

    private final RecognitionParam recognitionParam;

    private final IInterviewReportService interviewReportService;

    /**
     * 上传简历
     * @param chatId
     * @param file
     * @return
     */
    @PostMapping("/upload/{chatId}")
    @Operation(summary = "上传简历")
    public AjaxResult uploadPdf(@PathVariable String chatId, @RequestParam("file") MultipartFile file) {
        try {
            // 1. 校验文件是否为PDF格式
            if (!Objects.equals(file.getContentType(), "application/pdf")) {
                throw new RuntimeException("只能上传PDF文件！");
            }
            // 2.保存文件
            return fileRepository.save(chatId, file);
        } catch (Exception e) {
            log.error("Failed to upload PDF.", e);
            throw new RuntimeException("上传文件失败！");
        }
    }

    /**
     * 将pdf写入向量库
     * @param resource
     */
    private void writeToVectorStore(Resource resource) {
        // 1.创建PDF的读取器
        PagePdfDocumentReader reader = new PagePdfDocumentReader(
                resource, // 文件源
                PdfDocumentReaderConfig.builder()
                        .withPageExtractedTextFormatter(ExtractedTextFormatter.defaults())
                        .withPagesPerDocument(1) // 每1页PDF作为一个Document
                        .build()
        );
        // 2.读取PDF文档，拆分为Document
        List<Document> documents = reader.read();
        // 3.写入向量库
        vectorStore.add(documents);
    }

    /**
     * 发送面试会话到websocket
     * @param prompt
     * @param chatId
     * @return
     * @throws InterruptedException
     */
    @PostMapping("/chat")
    @Operation(summary = "面试会话")
    public Flux<String> chat(String prompt, String chatId, String position) throws InterruptedException {
//        webSocketInterviewServer.sendMessageToAI(prompt, chatId);
        return memberInterviewService.chat(prompt, chatId, position);
    }

    @GetMapping("/streamChat")
    @Operation(summary = "AI回复转语音合成")
    public void streamChat(String prompt, String chatId, String position) throws Exception {
        Flux<String> responseStream = memberInterviewService.chat(prompt, chatId, position).cache();
        webSocketInterviewServer.sendMessageToAI(chatId, responseStream);
        ttsService.streamInputOutput(Flowable.fromPublisher(responseStream.share()), chatId);
    }

    @PostMapping("/audioToText")
    @Operation(summary = "语音识别")
    public AjaxResult uploadAudio(@RequestBody byte[] audioData) throws IOException {
        if (audioData == null || audioData.length == 0) {
            throw new RuntimeException("音频数据为空");
        }

        // 创建临时文件保存音频
        Path tempDir = Files.createTempDirectory("audio_");
        Path targetPath = tempDir.resolve("recorded_audio.wav"); // 可根据需要改为 .wav 等格式

        // 写入文件
        Files.write(targetPath, audioData);

        System.out.println("音频已保存至：" + targetPath.toAbsolutePath());
        System.out.println("文件大小：" + audioData.length + " bytes");

        try {
            Recognition recognizer = new Recognition();
                Object result = recognizer.call(recognitionParam, new File(targetPath.toString()));
            JSONObject jsonObject = JSONUtil.parseObj(result);
            JSONArray sentences = jsonObject.getJSONArray("sentences");
            Object sentence = sentences.get(0);
            JSONObject sentenceObject = JSONUtil.parseObj(sentence);
            String text = sentenceObject.getStr("text");
            // 语音识别成功后删除临时文件
            Files.deleteIfExists(targetPath);
            return AjaxResult.success(text);
        } catch (Exception e) {
            log.error("语音识别或文件处理失败", e);
            throw new RuntimeException("语音识别失败！");
        }
    }

    @GetMapping("/report/list")
    @Operation(summary = "面试报告列表")
    public AjaxResult list(Integer pageNum, Integer pageSize) {
        Long userId = UserThreadLocal.getUserId();
        LambdaQueryWrapper<InterviewReport> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(InterviewReport::getMemberId, userId);
        queryWrapper.orderByDesc(InterviewReport::getCreateTime);
        Page pageInfo = new Page(pageNum, pageSize);
        interviewReportService.page(pageInfo, queryWrapper);
        return success(pageInfo);
    }

    @GetMapping("/report/{id}")
    @Operation(summary = "面试报告详情")
    public AjaxResult reportDetail(@PathVariable Long id) {
        return AjaxResult.success(interviewReportService.getById(id));
    }
}
